﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

#region ClassDescription
/* The Logger is used to format usefull informations depending on the sender.
 * The senders cant directly use the Logger.
 * They have to use a Handler.
 * The Handler is instantiated with the sender informations.
 * Those informations permit to the Logger to broadcast personalised informations.
 */
#endregion

namespace BomberManServer
{
    public class Logger
    {
        private List<Thread> threads;

        // Thread
        public class Thread
        {
            public delegate void MessageHandler(string message);
            public MessageHandler Message;

            private Logger logger;
            public bool available { get; private set; }
            private LinkedList<string> messages;

            public Thread(Logger logger)
            {
                this.logger = logger;
                available = false;
                messages = new LinkedList<string>();
            }

            public void send(string message)
            {
                messages.AddLast(message);
                available = true;
            }

            public Handler createHandler(string name)
            {
                Handler handler = new Handler(this, name);
                return handler;
            }

            // must check available before calling this
            public string read()
            {
                // maybe put a mutex
                string message = messages.First.Value;
                messages.RemoveFirst();
                if (messages.Count == 0) available = false;
                return message;
            }
        }

        // Nested Class used to access the parent object
        public class Handler
        {
            private Thread thread;
            private string name;

            // attach to the parent
            public Handler(Thread thread, string name)
            {
                this.thread = thread;
                this.name = name;
            }

            // methods to use the parent object
            // brodcast a simple message
            public void information(string content) 
            {
                //thread.send("[" + name + "] " + content + "\n"); 
            }
            // broadcast a message error
            public void error(string content) 
            {
                //thread.send("[" + name + "] " + content + "\n"); 
            }
            // broadcast a hint
            public void hint() { }
        }

        public Logger()
        {
            threads = new List<Thread>();
        }

        // dispatch all messages 
        public void dispatch()
        {
            foreach (Thread thread in threads)
            {
                while(thread.available)
                    if (thread.Message != null) thread.Message(thread.read());
            }
        }

        public Thread createThread()
        {
            Thread thread = new Thread(this);
            threads.Add(thread);
            return thread;
        }
    }
}
